package org.huzhp.console.service.impl;


import org.huzhp.console.config.GatewayConfig;
import org.huzhp.console.dao.*;
import org.huzhp.console.entity.*;
import org.huzhp.console.entity.vo.GatewayRouteVo;
import org.huzhp.console.entity.vo.SentinelRuleVo;
import org.huzhp.console.service.IConsoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 实现类
 * @Author: huzp
 * @CreateDate: 2020/3/12 15:40
 * @Version: 1.0
 */
@Service
public class ConsoleServiceImpl implements IConsoleService {

    private static final String GATEWAY_ROUTE_API = "/gateway/route";
    private static final String GATEWAY_RULE_API = "/gateway/rule";

    @Autowired
    private GatewayRouteMapper routeMapper;

    @Autowired
    private GatewayPredicateMapper predicateMapper;

    @Autowired
    private GatewayFilterMapper filterMapper;

    @Autowired
    private SentinelRuleMapper sentinelRuleMapper;

    @Autowired
    private SentinelParamMapper sentinelParamMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private GatewayConfig gatewayConfig;

    @Override
    public GatewayRouteVo findRouteByRouteId(String routeId) {
        return routeMapper.findRouteByRouteId(routeId);
    }

    @Override
    @Transactional
    public void saveRoute(GatewayRouteVo route) {

        GatewayRouteVo exist = routeMapper.findRouteByRouteId(route.getRouteId());
        if (exist == null) {
            GatewayRoute baseRoute = route.build();
            routeMapper.insert(baseRoute);

            route.getPredicates().forEach(predicateVo -> {
                GatewayPredicate predicate = predicateVo.build();
                predicate.setRouteId(baseRoute.getId());
                predicateMapper.insert(predicate);
            });

            route.getFilters().forEach(filterVo -> {
                GatewayFilter filter = filterVo.build();
                filter.setRouteId(baseRoute.getId());
                filterMapper.insert(filter);
            });

            //调用网关接口

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity formEntity = new HttpEntity<>(route.buildGatewayJson(), headers);
            restTemplate.postForEntity(gatewayConfig.getServer() + GATEWAY_ROUTE_API, formEntity, Void.TYPE);

        }

    }

    @Override
    @Transactional
    public void deleteRoute(String routeId) {
        restTemplate.delete(gatewayConfig.getServer() + GATEWAY_ROUTE_API + "/" + routeId);
        GatewayRouteVo route = routeMapper.findRouteByRouteId(routeId);
        if (route == null) {
            return;
        }
        routeMapper.deleteById(route.getId());

        Map<String, Object> param = new HashMap<>();
        param.put("route_id", route.getId());
        predicateMapper.deleteByMap(param);

        filterMapper.deleteByMap(param);
    }

    @Override
    public List getAllRoutes() {
        List<GatewayRouteVo> routeVos = routeMapper.findAll();
        return routeVos.stream().map(route -> route.buildGateway()).collect(Collectors.toList());
    }

    @Override
    public SentinelRuleVo findRuleByRuleResource(String ruleResource) {
        return sentinelRuleMapper.findRuleByRuleResource(ruleResource);
    }

    @Override
    public void saveRule(SentinelRuleVo ruleVo) {
        SentinelRuleVo exist = sentinelRuleMapper.findRuleByRuleResource(ruleVo.getRuleResource());
        if (exist == null) {
            SentinelRule rule = ruleVo.build();
            sentinelRuleMapper.insert(rule);

            SentinelParam param = ruleVo.getParam().build();
            param.setRuleId(rule.getId());
            sentinelParamMapper.insert(param);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity formEntity = new HttpEntity<>(ruleVo.buildGatewayJson(), headers);
            restTemplate.postForEntity(gatewayConfig.getServer() + GATEWAY_RULE_API, formEntity, Void.TYPE);
        }
    }

    @Override
    public void deleteRule(String ruleResource) {
        restTemplate.delete(gatewayConfig.getServer() + GATEWAY_RULE_API + "/" + ruleResource);
        SentinelRuleVo rule = sentinelRuleMapper.findRuleByRuleResource(ruleResource);
        if (rule == null) {
            return;
        }
        routeMapper.deleteById(rule.getId());

        Map<String, Object> param = new HashMap<>();
        param.put("rule_id", rule.getId());
        sentinelParamMapper.deleteByMap(param);

    }

    @Override
    public List getAllRules() {
        List<SentinelRuleVo> ruleVos = sentinelRuleMapper.findAll();
        return ruleVos.stream().map(rule -> rule.buildGateway()).collect(Collectors.toList());
    }
}
